﻿#include "jcereader.h"

JceReader::JceReader(const QByteArray &data):DataReader(data)
{

}

JceReader::HeadData::HeadData(JceReader &reader)
{
    qint8 value;
    reader.readByte(value);
    type = (JceDataType)(value & 15);
    tag = (value & 0xF0) >> 4;
    if(tag == 15)reader.readByte(tag);
}

JceReader &JceReader::setServerEncoding(bool isGBK)
{
    sServerEncodingGBK = isGBK;
    return *this;
}

JceReader &JceReader::parseObj(QVariant &ret)
{
    int nouse = 0;
    parseObj(ret,nouse,false);
    return *this;
}

QVariantMap JceReader::parseObj()
{
    QVariant ret = QVariantMap();
    int nouse = 0;
    parseObj(ret,nouse,false);
    return ret.toMap();
}

JceReader &JceReader::setData(const QByteArray &data)
{
    DataReader::setData(data);
    return *this;
}

QVariantMap &JceReader::convertQVMap(QVariant &data)
{
    return *(QVariantMap*)data.data();
}

void JceReader::parseObj(QVariant &ret, int & retTag,bool readOnce)
{
    while (getUnReadSize() > 0) {
        HeadData head(*this);
        switch (head.type) {
        case JceDataType::BYTE:{
            qint8 tmp;readByte(tmp);
            retValue(ret,retTag,tmp,head.tag,readOnce);
        }break;
        case JceDataType::DOUBLE:{
            double tmp;readDouble(tmp);
            retValue(ret,retTag,tmp,head.tag,readOnce);
        }break;
        case JceDataType::FLOAT:{
            float tmp;readFloat(tmp);
            retValue(ret,retTag,tmp,head.tag,readOnce);
        }break;
            case JceDataType::INT:{
            int tmp;readInt(tmp);
            retValue(ret,retTag,tmp,head.tag,readOnce);
        }break;
        case JceDataType::LIST:{
            QList<QVariant> tmp;
            QVariant size;int sizeTag;
            parseObj(size,sizeTag,true);//seem the
            sizeTag = size.toInt();//any number type to int
            if(sizeTag < 0)abort();
            for(int i=0;i<sizeTag;++i){
                QVariant elem;int elemTag;
                parseObj(elem,elemTag,true);
                tmp.append(elem);
            }
            retValue(ret,retTag,tmp,head.tag,readOnce);
        }break;
        case JceDataType::LONG:{
            qint64 tmp;readLong(tmp);
            retValue(ret,retTag,tmp,head.tag,readOnce);
        }break;
        case JceDataType::MAP:{
            //QMap<QVariant,QVariant> tmp;
            QVariantMap tmp;
            QVariant size;int sizeTag;
            parseObj(size,sizeTag,true);//seem the
            sizeTag = size.toInt();//any number type to int
            if(sizeTag < 0)abort();
            for(int i=0;i<sizeTag;++i){
                QVariant keyElem;int keyElemTag;
                parseObj(keyElem,keyElemTag,true);
                QVariant valueElem;int valueElemTag;
                parseObj(valueElem,valueElemTag,true);
                tmp[keyElem.toString()] = valueElem;//TODO
            }
            retValue(ret,retTag,QVariant::fromValue(tmp),head.tag,readOnce);
        }break;
        case JceDataType::SHORT:{
            short tmp;readShort(tmp);
            retValue(ret,retTag,tmp,head.tag,readOnce);
        }break;
        case JceDataType::SIMPLE_LIST:{
            skipBytes(1);
            QVariant size;int sizeTag;
            parseObj(size,sizeTag,true);//seem the
            sizeTag = size.toInt();//any number type to int
            if(sizeTag < 0)abort();
            QByteArray data;
            readRaw(data,sizeTag);
            retValue(ret,retTag,data,head.tag,readOnce);
        }break;
        case JceDataType::STRING1:{
            QByteArray data;
            qint8 tmp;readByte(tmp);
            int size = tmp;
            if(size < 0)size += 0x100;
            readRaw(data,size);
            retValue(ret,retTag,data,head.tag,readOnce);
        }break;
        case JceDataType::STRING4:{
            int size;readInt(size);
            if(size < 0)abort();
            QByteArray data;
            readRaw(data,size);
            retValue(ret,retTag,data,head.tag,readOnce);
        }break;
        case JceDataType::STRUCT_BEGIN:{
            QVariant data = QVariantMap();int tag;
            parseObj(data,tag,false);
            retValue(ret,retTag,data,head.tag,readOnce);
        }break;
        case JceDataType::STRUCT_END:{
            return;//we just read one object
        }break;
        case JceDataType::ZERO_TYPE:break;
        }
        if(readOnce)break;
    }
}

void JceReader::retValue(QVariant &ret,int & retTag, QVariant obj, int tag, bool readOnce)
{
    if(!readOnce){
        ((QVariantMap*)ret.data())->insert(QString::number(tag),obj);
    }else {
        ret = obj;
        retTag = tag;
    }
}

/*
JceReader &JceReader::skipToTag(int tag)
{

}

JceReader &JceReader::readHead(JceReader::JceDataType type)
{

}

JceReader &JceReader::readInt(int tag, int &data)
{

}

JceReader &JceReader::readByte(int tag, qint8 &data)
{

}

JceReader &JceReader::readShort(int tag, short &data)
{

}

JceReader &JceReader::readLong(int tag, qint64 &data)
{

}

JceReader &JceReader::readNull(int tag)
{

}

JceReader &JceReader::readBytes(int tag, QByteArray &data)
{

}

JceReader &JceReader::readString(int tag, QString &data)
{

}

JceReader &JceReader::readFloat(int tag, float &data)
{

}

JceReader &JceReader::readDouble(int tag, double &data)
{

}

JceReader &JceReader::readStruct(int tag, JceReader &data)
{

}

JceReader &JceReader::setData(const QByteArray &data)
{
    setData(data);
    return *this;
}
*/
